package com.api.rc.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.api.core.ServiceException;
import com.api.core.config.AuthUser;
import com.api.rc.interceptor.LobbyHandshakeInterceptor;
import com.api.rc.lobby.LobbyManager;
import com.api.rc.lobby.message.LobbyEvent;
import com.api.rc.lobby.message.LobbyMessage;
import com.api.rc.lobby.message.MessageGenerator;
import com.api.user.service.UserInfoService;
import com.api.user.vo.UserInfoVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.util.Collections;
import java.util.Map;
import java.util.Optional;

/**
 * @author RenQiang
 * @date 2021/7/17
 */
@Slf4j
public class LobbyWebSocketHandler extends TextWebSocketHandler {
    private final LobbyManager lobbyManager;
    private final UserInfoService userInfoService;

    public LobbyWebSocketHandler(LobbyManager lobbyManager, UserInfoService userInfoService) {
        this.lobbyManager = lobbyManager;
        this.userInfoService = userInfoService;
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        AuthUser authUser = (AuthUser) Optional.ofNullable((UsernamePasswordAuthenticationToken) session.getPrincipal())
                .map(UsernamePasswordAuthenticationToken::getPrincipal)
                .orElse(null);
        if (authUser == null) {
            throw new ServiceException("This currect user is not logged in");
        }
        log.info("快速挑战大厅>>客户端连接成功: {} => {}", session.getRemoteAddress(), authUser.getId());
        Long roomId = (Long) session.getAttributes().get(LobbyHandshakeInterceptor.ROOM_ID_KEY);
        try {
            Map<Long, UserInfoVo> userIdVoMap = userInfoService.getIdVoMap(Collections.singletonList(authUser.getId()));
            lobbyManager.joinRoom(userIdVoMap.get(authUser.getId()), roomId, session);
        } catch (IllegalArgumentException e) {
            session.sendMessage(MessageGenerator.genSystemMessage(LobbyEvent.SERVER_JOIN_ROOM_FAILED, e.getMessage()));
            session.close();
            log.error("快速挑战大厅>>加入房间失败, 断开连接 ==> userId: {}, roomId: {}", authUser.getId(), roomId);
        }
    }

    public static void main(String[] args) {
        System.out.println(Integer.MAX_VALUE);
        Integer a = new LobbyMessage<>(LobbyEvent.HEART_BEAT, Integer.parseInt(String.valueOf("2147483648"))).getData();
        System.out.println(a);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        AuthUser authUser = (AuthUser) Optional.ofNullable((UsernamePasswordAuthenticationToken) session.getPrincipal())
                .map(UsernamePasswordAuthenticationToken::getPrincipal)
                .orElse(null);
        if (authUser == null) {
            throw new ServiceException("This currect user is not logged in");
        }
        LobbyMessage<?> lobbyMessage;
        try {
            lobbyMessage = JSON.parseObject(message.getPayload(), LobbyMessage.class);
            switch (lobbyMessage.getEvent()) {
                case HEART_BEAT:
                    TextMessage heartBeatMsg = MessageGenerator.genHeartBeatMsg();
                    session.sendMessage(heartBeatMsg);
                    break;
                case CLIENT_JOIN_TEAM:
                    Integer teamNo = (Integer) lobbyMessage.getData();
                    lobbyManager.joinTeam(authUser.getId(), teamNo);
                    break;
                case CLIENT_READY_TO_GAME:
                    lobbyManager.readyToGame(authUser.getId());
                    break;
                default:
                    log.error("不支持的消息类型: {} => {}", session.getRemoteAddress(), message);
                    session.close();
                    break;
            }
        } catch (JSONException e) {
            log.error("快速挑战大厅>>收到异常消息, 关闭连接: {} => {}", session.getRemoteAddress(), message, e);
            session.close();
        } catch (IllegalArgumentException e) {
            log.error("快速挑战大厅>>处理消息失败: {} => {}", session.getRemoteAddress(), e.getMessage());
            session.sendMessage(MessageGenerator.genSystemMessage(LobbyEvent.SERVER_UNSUPPORTED_OPERATION, e.getMessage()));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Optional.ofNullable((UsernamePasswordAuthenticationToken) session.getPrincipal())
                .map(token -> (AuthUser) token.getPrincipal())
                .ifPresent(authUser -> lobbyManager.exitRoom(authUser.getId()));
        log.info("快速挑战大厅>>客户端断开连接: {} => {}", session.getRemoteAddress(), status);
    }
}
